import { nmAppErrorLog, removeObject } from '@app-nextmesh/common/utils';
import { showLoading } from '@app-nextmesh/components';
import {
  IMenuItem,
  ITreeNode,
  onTreeEventUpdate,
  TreeNodeType,
} from '@app-nextmesh/components/types';
import { documentV2 } from '@app-nextmesh/domain';
import { useProjectStore } from '@app-nextmesh/store/project';
import { useSimulationsStore } from '@app-nextmesh/store/simulations';
import { LeftPanelEventType } from '@app-nextmesh/types';
import { events } from '@app-nextmesh/utils';
import {
  toLocalSimulation,
  toLocalTask,
  toLocalVisualization,
} from '@app-nextmesh/widgets/LeftPanel/data';
import { cloneDeep } from 'lodash';
import { useCallback, useEffect, useState } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import ResultAlertDialog from './BusinessDialog/ResultAlertDialog';
import SimulationAddDialog from './BusinessDialog/SimulationAddDialog';
import SimulationAlertDialog from './BusinessDialog/SimulationAlertDialog';
import TaskAddDialog from './BusinessDialog/TaskAddDialog';
import TaskAlertDialog from './BusinessDialog/TaskAlertDialog';
import VisualizationAlertDialog from './BusinessDialog/VisualizationAlertDialog';
import VisualizationItemAlertDialog from './BusinessDialog/VisualizationItemAlertDialog';

export default function Dialogs() {
  const [showDialog, setShowDialog] = useState({ show: false, node: null });
  const projectInfo = useProjectStore((state) => state.projectInfo);
  const { simulations, setSimulations } = useSimulationsStore();

  const handleClose = useCallback(
    () => setShowDialog({ show: false, node: null }),
    [],
  );

  const showDialogListener = (
    data: ITreeNode,
    menu: IMenuItem,
    onUpdate: onTreeEventUpdate,
  ) => {
    setShowDialog({ show: false, node: null });
    switch (menu.value) {
      case 'addition':
        showAdditionDialog(data, menu, onUpdate);
        break;
      case 'delete':
        showDelAlertDialog(data, menu, onUpdate);
        break;
    }
  };
  const showAdditionDialog = (
    data: ITreeNode,
    menu: IMenuItem,
    onUpdate: onTreeEventUpdate,
  ) => {
    switch (data.type) {
      case TreeNodeType.Simulations: // 仿真列表添加仿真
        setShowDialog({
          show: true,
          node: (
            <SimulationAddDialog
              count={data.children?.length ?? 0}
              onClose={handleClose}
              onOk={(newData) => {
                setShowDialog({ show: false, node: null });
                const simus = simulations ?? [];
                setSimulations([...simus, newData]);
                onUpdate(toLocalSimulation(newData), menu, true);
              }}
            />
          ),
        });
        break;
      case TreeNodeType.Tasks: // 求解（任务）列表添加任务
        setShowDialog({
          show: true,
          node: (
            <TaskAddDialog
              count={data.children?.length ?? 0}
              onClose={handleClose}
              onOk={(newData) => {
                setShowDialog({ show: false, node: null });
                onUpdate(toLocalTask(newData), menu, true);
              }}
            />
          ),
        });
        break;
    }
  };
  const getFormIndex = (id: string) => {
    const idSplit = id.split('-');
    const formIndexStr = idSplit[idSplit.length - 1]; // 最后一个是对应表单的index
    let formIndex = parseInt(formIndexStr);
    if (isNaN(formIndex)) formIndex = undefined;
    return formIndex;
  };
  const doRequest = async (request: Promise<any>) => {
    const hide = showLoading();
    try {
      return await request;
    } catch (error) {
      nmAppErrorLog('Dialogs', 'doRequest', error);
    } finally {
      hide();
    }
    return null;
  };

  const showDelAlertDialog = (
    data: ITreeNode,
    menu: IMenuItem,
    onUpdate: (newData: ITreeNode, menu?: IMenuItem) => void,
  ) => {
    let fi: number;
    switch (data.type) {
      case TreeNodeType.Simulation:
        setShowDialog({
          show: true,
          node: (
            <SimulationAlertDialog
              uuid={data.id}
              onClose={handleClose}
              onOk={() => {
                setShowDialog({ show: false, node: null });
                const findIndex = simulations.findIndex(
                  (simulation) => simulation.uuid === data.id,
                );
                if (findIndex !== -1) {
                  simulations.splice(findIndex, 1);
                }
                setSimulations([...simulations]);
                onUpdate(data, menu);
              }}
            />
          ),
        });
        break;
      case TreeNodeType.Task:
        setShowDialog({
          show: true,
          node: (
            <TaskAlertDialog
              uuid={data.id}
              onClose={handleClose}
              onOk={() => {
                setShowDialog({ show: false, node: null });
                onUpdate(data, menu);
              }}
            />
          ),
        });
        break;
      case TreeNodeType.Result:
        setShowDialog({
          show: true,
          node: (
            <ResultAlertDialog
              uuid={data.formData.uuid}
              onClose={handleClose}
              onOk={() => {
                setShowDialog({ show: false, node: null });
                onUpdate(data, menu);
              }}
            />
          ),
        });
        break;
      case TreeNodeType.Visualization:
        setShowDialog({
          show: true,
          node: (
            <VisualizationAlertDialog
              uuid={data.id}
              onClose={handleClose}
              onOk={() => {
                setShowDialog({ show: false, node: null });
                onUpdate(data, menu);
              }}
            />
          ),
        });
        break;
      case TreeNodeType.VisualizationDerived:
        fi = getFormIndex(data.id);
        setShowDialog({
          show: true,
          node: (
            <VisualizationItemAlertDialog
              data={data}
              name='derived'
              formIndex={fi}
              onClose={handleClose}
              onUpdate={(newData) => {
                setShowDialog({ show: false, node: null });
                onUpdate(toLocalVisualization(newData));
              }}
            />
          ),
        });
        break;
      case TreeNodeType.VisualizationPlot:
        fi = getFormIndex(data.id);
        setShowDialog({
          show: true,
          node: (
            <VisualizationItemAlertDialog
              data={data}
              name='plots'
              formIndex={fi}
              onClose={handleClose}
              onUpdate={(newData) => {
                setShowDialog({ show: false, node: null });
                onUpdate(toLocalVisualization(newData));
              }}
            />
          ),
        });
        break;
      default:
        {
          // 根据data.type动态显示delete dialog
          const dataType = data.type;
          if (!dataType) {
            return;
          }
          // data.id 格式： 52e6373e-6453-490b-a187-501ec68200d0-condition.boundaries.5
          // const formIndex = getFormIndex(data.id);
          // 根据 dataType 判断使用哪个模块的删除
          if (dataType.startsWith(TreeNodeType.Simulation)) {
            // dataType 格式： simulation-CFD-流体力学C-boundaries-SYMMETRY

            // 从id中解析出jsonPath，通过jsonPath获取对应的form
            const jsonPath = data.id.split('-').pop();

            const formData = cloneDeep(data.formData);
            removeObject(formData, jsonPath);
            // 删除后再更新
            doRequest(documentV2.updateSimulation(formData)).then((newData) => {
              // 全量更新整个simulation，因为叶子节点的id可能发生改变
              newData && onUpdate(toLocalSimulation(newData));
            });
          }
        }
        break;
    }
  };
  useEffect(() => {
    events.on(LeftPanelEventType.MenuClick, showDialogListener);
    return () => {
      events.off(LeftPanelEventType.MenuClick, showDialogListener);
    };
  }, [projectInfo]);
  return (
    <>
      {showDialog.show ? (
        <ErrorBoundary
          fallback={<></>}
          onError={() => setShowDialog({ show: false, node: null })}>
          {showDialog.node}
        </ErrorBoundary>
      ) : null}
    </>
  );
}
